package com.apa7.keepaccounts.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.apa7.keepaccounts.dao.BillDao;
import com.apa7.keepaccounts.entity.Bill;
import com.apa7.keepaccounts.entity.User;
import com.apa7.keepaccounts.service.StatisticsService;
import com.apa7.keepaccounts.service.UserService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import net.sourceforge.pinyin4j.PinyinHelper;
import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;
import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;
import net.sourceforge.pinyin4j.format.HanyuPinyinVCharType;
import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

@Service
public class StatisticsImpl implements StatisticsService{

    private static Logger logger = LoggerFactory.getLogger(StatisticsImpl.class);
    @Autowired
    private UserService userService;
    @Autowired
    private BillDao billDao;
    @Autowired
    private HanyuPinyinOutputFormat defaultFormat;

    private User user;
    private Date dateStart;
    private Date dateEnd;

    /**
     * 统计页面的首页
     *
     * @param key  用户的key值
     * @param date 获取的时间格式为2019-05
     * @return list
     */
    @Override
    public JSONObject index(String key, String date){
        //获取用户
        boolean isSuccess=getUserAndProcessed(key,date);
        if(!isSuccess)return null;

        //从数据库获取信息
        QueryWrapper<Bill> qw=new QueryWrapper<>();
        qw.select("pay_type as payType","money","time","bill_id as BillId","pay_type_img","pay_mode").lambda()
                .eq(Bill::getUserId,user.getUserId())
                .ge(Bill::getTime,dateStart.getTime()/1000)
                .lt(Bill::getTime,dateEnd.getTime()/1000)
                .orderByDesc(Bill::getTime);
        List<Bill> bill=billDao.selectList(qw);

        //循环处理数据
        Map<String,List<JSONObject>> list=new TreeMap<>(new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                // 降序排列
                return o2.compareTo(o1);
            }
        });
        JSONObject listObject=null;
        SimpleDateFormat sdf=new SimpleDateFormat("MM-dd");
        List<JSONObject> dateList=null;
        String time="";
        int totalExpenditure=0;
        for(Bill v: bill) {
            listObject=new JSONObject();
            time=sdf.format(new Date(v.getTime()*1000));
            listObject.put("name",v.getPayType());
            listObject.put("money",v.getMoney());
            listObject.put("billId",v.getBillId());
            listObject.put("img",v.getPayTypeImg());
            listObject.put("time",v.getTime());
            listObject.put("payMode",v.getPayMode());
            totalExpenditure+=v.getMoney();

            if(list.containsKey(time)){
                dateList=list.get(time);
                dateList.add(listObject);
                list.put(time,dateList);
            }else{
                dateList=new ArrayList<JSONObject>();
                dateList.add(listObject);
                list.put(time,dateList);
            }
        }
        dateList=null;
        sdf=null;

        JSONObject returnData=new JSONObject();
        returnData.put("totalExpenditure",totalExpenditure);
        returnData.put("list",list);
        return returnData;
    }

    /**
     * 获取图表数据
     *
     * @param key  用户的key值
     * @param date 获取的时间格式为2019-05
     * @return list
     */
    @Override
    public JSONObject chart(String key, String date) {
        //获取用户
        boolean isSuccess=getUserAndProcessed(key,date);
        if(!isSuccess)return null;

        //获取当月所有记录
        QueryWrapper<Bill> qw=new QueryWrapper<>();
        qw.select("pay_type as payType","money","time","pay_mode as payMode").lambda()
                .eq(Bill::getUserId,user.getUserId())
                .ge(Bill::getTime,dateStart.getTime()/1000)
                .lt(Bill::getTime,dateEnd.getTime()/1000)
                .orderByDesc(Bill::getTime);
        List<Bill> bill=billDao.selectList(qw);

        //循环处理
        String ModeKeyPingYing="",TypeKeyPingYing="";
        int totalMoney = 0;
        JSONObject payModeJSONObject,payTypeJSONObject;
        List<JSONObject> payMode=new ArrayList<>(),payType=new ArrayList<>();//支出方式,支出类型记录
        JSONObject payModeK=new JSONObject(),payTypeK=new JSONObject();//支出方式,支出类型的key值记录
        for(Bill v:bill){
            ModeKeyPingYing=toHanyuPinyin(v.getPayMode());
            TypeKeyPingYing=toHanyuPinyin(v.getPayType());

            //支出方式处理
            if(payModeK.containsKey(ModeKeyPingYing)){
                payModeJSONObject=payMode.get(payModeK.getIntValue(ModeKeyPingYing));
                payModeJSONObject.put("data",payModeJSONObject.getIntValue("data")+v.getMoney());
                payMode.set(payModeK.getIntValue(ModeKeyPingYing),payModeJSONObject);
            }else{
                payModeJSONObject=new JSONObject();
                payModeJSONObject.put("name",v.getPayMode());
                payModeJSONObject.put("data",v.getMoney());
                payMode.add(payModeJSONObject);
                payModeK.put(ModeKeyPingYing,payMode.size()-1);
            }

            //支出类型处理
            totalMoney+=v.getMoney();
            if(payTypeK.containsKey(TypeKeyPingYing)){
                payTypeJSONObject=payType.get(payTypeK.getIntValue(TypeKeyPingYing));
                payTypeJSONObject.put("data",payTypeJSONObject.getIntValue("data")+v.getMoney());
                payType.set(payTypeK.getIntValue(TypeKeyPingYing),payTypeJSONObject);
            }else{
                payTypeJSONObject=new JSONObject();
                payTypeJSONObject.put("name",v.getPayType());
                payTypeJSONObject.put("data",v.getMoney());
                payType.add(payTypeJSONObject);
                payTypeK.put(TypeKeyPingYing,payType.size()-1);
            }
        }

        JSONObject returnData=new JSONObject();
        returnData.put("payMode",payMode);
        returnData.put("payType",payType);
        returnData.put("totalMoney",totalMoney);

        return returnData;
    }

    /**
     * 获取用户以及处理时间
     * @param key 用户的key
     * @param date 时间 格式2019-06-06
     * @return
     */
    private boolean getUserAndProcessed(String key, String date){
        //获取用户
        user=userService.getInfo(key);
        if(user==null)return false;

        //转换时间格式
        try {
            SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM");
            dateStart = simpleDateFormat.parse(date);
            Calendar rightNow = Calendar.getInstance();
            rightNow.setTime(dateStart);
            rightNow.add(Calendar.MONTH, 1);
            dateEnd = rightNow.getTime();
        }catch (ParseException e){
            logger.info("转换日期失败！！！");
            logger.info("日期数据为：");
            logger.info(date);
            return false;
        }

        return true;
    }

    /**
     * 将文字转为汉语拼音
     * @param ChineseLanguage 要转成拼音的中文
     */
    private String toHanyuPinyin(String ChineseLanguage){
        char[] cl_chars = ChineseLanguage.trim().toCharArray();
        StringBuilder hanyupinyin = new StringBuilder();
        defaultFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE); // 输出拼音全部小写
        defaultFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE); // 不带声调
        defaultFormat.setVCharType(HanyuPinyinVCharType.WITH_V) ;
        try {
            for (int i=0; i<cl_chars.length; i++){
                if (String.valueOf(cl_chars[i]).matches("[\u4e00-\u9fa5]+")){// 如果字符是中文,则将中文转为汉语拼音
                    hanyupinyin.append(PinyinHelper.toHanyuPinyinStringArray(cl_chars[i], defaultFormat)[0]);
                } else {// 如果字符不是中文,则不转换
                    hanyupinyin.append(cl_chars[i]);
                }
            }
        } catch (BadHanyuPinyinOutputFormatCombination e) {
            return "";
        }
        return hanyupinyin.toString();
    }
}
